package com.javaspeak.designpatterns.go4.behavioural.mediator;

/**
 * A ChatUser communicates with other ChatUsers using the mediator,
 * ChatMediator. Only the ChatMediator has reference to all ChatUsers.
 * <p>
 * The mediator design pattern is about the Mediator only having reference
 * to all consumers and producers.  In this example the ChatUsers are both
 * consumers and producers: they can both send and receive messages.
 *
 * @author John Dickerson
 */
public class ChatUserImpl implements ChatUser, Comparable<ChatUserImpl> {

    private String userId;
    private ChatMediator chatMediator;


    /**
     * The ChatMediator is passed to each ChatUser implementation. The ChatUser
     * makes calls to the ChatMediator to send messages to other ChatUsers
     *
     * @param chatMediator The ChatMediator holds references to other ChatUsers
     * @param userId The userId of this ChatUser
     */
    public ChatUserImpl( ChatMediator chatMediator, String userId ){

        this.chatMediator = chatMediator;
        this.userId = userId;
    }


    /* (non-Javadoc)
     * @see com.javaspeak.designpatterns.go4.behavioural.mediator.
     *      ChatUser#getUserId()
     */
    @Override
    public String getUserId() {

        return userId;
    }


    /* (non-Javadoc)
     * @see com.javaspeak.designpatterns.go4.behavioural.mediator.
     *      ChatUser#sendMessage(java.lang.String, java.lang.String)
     */
    @Override
    public void sendMessage( String groupName, String message ) {

        chatMediator.sendMessage( groupName, this, message );
    }


    /* (non-Javadoc)
     * @see com.javaspeak.designpatterns.go4.behavioural.mediator.
     *      ChatUser#receiveMessage(java.lang.String, java.lang.String,
     *          java.lang.String)
     */
    @Override
    public void receiveMessage( String groupName, String userId, String message ) {

        System.out.println( this.userId + "> Received Message from : " +
                userId + " [group: " + groupName + "], message :\n    " +
                    message );
    }


    /* (non-Javadoc)
     * @see com.javaspeak.designpatterns.go4.behavioural.mediator.
     *      ChatUser#createNewGroup(java.lang.String)
     */
    @Override
    public boolean createNewGroup( String group ) {

        return chatMediator.createNewGroup( group );
    }


    /* (non-Javadoc)
     * @see com.javaspeak.designpatterns.go4.behavioural.mediator.
     *      ChatUser#subscribeToGroup(java.lang.String)
     */
    @Override
    public void subscribeToGroup( String groupName ) {

        chatMediator.subscribeToGroup( groupName, this );
    }


    /* (non-Javadoc)
     * @see com.javaspeak.designpatterns.go4.behavioural.mediator.
     *      ChatUser#getGroups()
     */
    @Override
    public String[] getGroups() {

        return chatMediator.getGroups();
    }


    /* (non-Javadoc)
     * @see com.javaspeak.designpatterns.go4.behavioural.mediator.
     *      ChatUser#groupExists(java.lang.String[], java.lang.String)
     */
    @Override
    public boolean groupExists(String[] groups, String groupName) {

        for ( String group : groups ){

            if ( groupName.equals( group ) ){

                return true;
            }
        }

        return false;
    }


    /* (non-Javadoc)
     * @see java.lang.Object#hashCode()
     */
    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result
                + ((chatMediator == null) ? 0 : chatMediator.hashCode());
        result = prime * result + ((userId == null) ? 0 : userId.hashCode());
        return result;
    }


    /* (non-Javadoc)
     * @see java.lang.Object#equals(java.lang.Object)
     */
    @Override
    public boolean equals(Object obj) {
        if (this == obj)
            return true;
        if (obj == null)
            return false;
        if (getClass() != obj.getClass())
            return false;
        ChatUserImpl other = (ChatUserImpl) obj;
        if (chatMediator == null) {
            if (other.chatMediator != null)
                return false;
        } else if (!chatMediator.equals(other.chatMediator))
            return false;
        if (userId == null) {
            if (other.userId != null)
                return false;
        } else if (!userId.equals(other.userId))
            return false;
        return true;
    }


    /* (non-Javadoc)
     * @see java.lang.Comparable#compareTo(java.lang.Object)
     */
    @Override
    public int compareTo(ChatUserImpl other) {

        return this.userId.compareTo( other.userId );
    }
}
